package com.wyw.function.learning.common;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Supplier;

/**
 * @Title
 * @Description
 * @Author Mr Wu yewen.wu.china@gmail.com
 * Update History:
 * Author        Time            Content
 */
public class MergeInfoService {

    private OrderService orderService = new OrderService();
    private MailService mailService = new MailService();
    private RefundService refundService = new RefundService();

    public MergeInfoVO getInfo(String orderId) {

        // 基于并行编排的查询流程
        // 优先查询订单，（有）并行查询其他服务，（没有）抛异常返回结果
        //            |---stage2---|
        // stage1-----              -----stage4
        //            |---stage3---|
        try {
            return CompletableFuture.supplyAsync(() -> {
                OrderVO orderVO = log(() -> orderService.queryByOrderId(orderId));
                if(orderVO == null) {
                    throw new IllegalArgumentException("orderVO is null");
                }
                return buildByOrder(orderVO);
            }).thenComposeAsync(vo -> {
                try {
                    CompletableFuture.allOf(
                            CompletableFuture.runAsync(() -> log(() -> buildByMail(vo, mailService.queryByOrderId(orderId)))),
                            CompletableFuture.runAsync(() -> log(() -> buildByRefund(vo, refundService.queryByOrderId(orderId))))
                    ).get();
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
                return CompletableFuture.completedFuture(vo);
            }).handleAsync((c, e) -> {
                if(e != null) {
                    return null;
                }
                return c;
            }).get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    private MergeInfoVO buildByOrder(OrderVO orderVO) {
        MergeInfoVO mergeInfoVO = new MergeInfoVO();
        mergeInfoVO.setOrderVO(orderVO);
        return mergeInfoVO;
    }

    private MergeInfoVO buildByMail(MergeInfoVO mergeInfoVO, MailVO mailVO) {
        mergeInfoVO.setMailVO(mailVO);
        return mergeInfoVO;
    }

    private MergeInfoVO buildByRefund(MergeInfoVO mergeInfoVO, RefundVO refundVO) {
        mergeInfoVO.setRefundVO(refundVO);
        return mergeInfoVO;
    }

    private static <T> T log(Supplier<T> supplier) {
        long start = System.currentTimeMillis();
        T t = supplier.get();
        System.out.println(System.currentTimeMillis() - start + ":ms");
        return t;
    }

}
